﻿namespace Creek.UI.EFML.Base.CSS
{
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Reflection;
    using System.Windows.Forms;

    using Creek.UI.EFML.Base.CSS.Converters;
    using Creek.UI.EFML.Base.EFML.Elements;
    using Creek.UI.EFML.Base.Exceptions;

    using ColorConverter = Creek.UI.EFML.Base.CSS.Converters.ColorConverter;
    using FontConverter = Creek.UI.EFML.Base.CSS.Converters.FontConverter;
    using ImageConverter = Creek.UI.EFML.Base.CSS.Converters.ImageConverter;
    using PaddingConverter = Creek.UI.EFML.Base.CSS.Converters.PaddingConverter;
    using SizeConverter = Creek.UI.EFML.Base.CSS.Converters.SizeConverter;

    internal class StyleChanger
    {
        #region Public Methods and Operators

        //[DebuggerStepThrough]
        public static void Execute(Document b, Control.ControlCollection cc)
        {
            foreach (StyleElement elementBase in b.Header.Styles.Where(elementBase => elementBase is StyleElement))
            {
                IEnumerable<CssParserRule> p = new CssParser().ParseAll(elementBase.Source);
                foreach (var cssParserRule in p)
                {
                    foreach (var selector in cssParserRule.Selectors)
                    {
                        foreach (var bb in cc)
                        {
                            if (bb is Control)
                            {
                                var bbb = bb as IUIElement;
                                if (bbb != null)
                                {
                                    if (bbb.style != null)
                                    {
                                        if ("#" + bbb.ID == selector)
                                        {
                                            ExecuteQuery(bbb.style, cssParserRule);
                                        }
                                        else if (selector == "body")
                                        {
                                            ExecuteQuery(bbb.style, cssParserRule);
                                        }
                                        else if (!selector.StartsWith("#"))
                                        {
                                            throw new CssException("'" + selector + "'- is not a valid sector");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region Methods

        private static void ExecuteQuery(IStyle bbb, CssParserRule cssParserRule)
        {
            foreach (var d in cssParserRule.Declarations)
            {
                PropertyInfo prop = bbb.GetType().GetProperty(d.Property);
                if (prop != null)
                {
                    if (prop.PropertyType.Name == typeof(Padding).Name)
                    {
                        prop.SetValue(bbb, new PaddingConverter().Convert(d.Value), null);
                    }
                    if (prop.PropertyType.Name == typeof(Size).Name)
                    {
                        prop.SetValue(bbb, new SizeConverter().Convert(d.Value), null);
                    }
                    if (prop.PropertyType.Name == typeof(Color).Name)
                    {
                        prop.SetValue(bbb, new ColorConverter().Convert(d.Value), null);
                    }
                    if (prop.PropertyType.Name == typeof(Font).Name)
                    {
                        prop.SetValue(bbb, new FontConverter().Convert(d.Value), null);
                    }
                    if (prop.PropertyType.Name == typeof(bool).Name)
                    {
                        prop.SetValue(bbb, new BoolConverter().Convert(d.Value), null);
                    }
                    if (prop.PropertyType.Name == typeof(Image).Name)
                    {
                        prop.SetValue(
                            bbb,
                            d.Value == "null"
                                ? new NullConverter().Convert(d.Value)
                                : new ImageConverter().Convert(d.Value), null);
                    }
                    if (prop.PropertyType.IsEnum)
                    {
                        prop.SetValue(bbb, EnumConverter.Convert(prop.PropertyType, d.Value), null);
                    }
                }
            }
        }

        #endregion
    }
}